package dao

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/patrickmn/go-cache"

	"bilinadmin/pkg/db/pgex"

	"bilinadmin/internal/model"
)

// PermissionDao Permission dao
type PermissionDao interface {
	// GetPermission 获取权限列表
	GetPermission(ctx context.Context) ([]*model.Permission, error)
	// GetPermissionByRouter 根据 router 获取权限
	GetPermissionByRouter(ctx context.Context, perType int8, router string) (*model.Permission, error)
	// GetPermissionById 根据 id 获取权限
	GetPermissionById(ctx context.Context, id int64) (*model.Permission, error)
}

var perDao PermissionDao

type perDaoImpl struct {
	*DaoBase
	name string
}

// InitPermissionDao 初始化 dao
func InitPermissionDao() {
	perDao = &perDaoImpl{
		DaoBase: daoBase,
		name:    "permission_dao",
	}
}

// GetPermissionDao 获取 dao
func GetPermissionDao() PermissionDao {
	return perDao
}

// GetPermission 获取权限列表
func (dao *perDaoImpl) GetPermission(ctx context.Context) ([]*model.Permission, error) {
	var pers []*model.Permission
	query := "SELECT * FROM permission WHERE deleted_at=0"
	err := dao.db.Query(ctx, &pers, query)
	return pers, err
}

var perCache = cache.New(6*time.Hour, 12*time.Hour)

// GetPermissionByRouter 根据 router 获取权限
func (dao *perDaoImpl) GetPermissionByRouter(ctx context.Context, perType int8, router string) (*model.Permission, error) {
	key := fmt.Sprintf("router:%d:%s", perType, router)
	if per, found := perCache.Get(key); found {
		return per.(*model.Permission), nil
	}
	per := &model.Permission{}
	query := "SELECT id, name, per_type, router FROM permission WHERE per_type=? AND router=? AND deleted_at=0"
	err := dao.db.Get(ctx, per, query, perType, router)
	if err != nil {
		if errors.Is(err, pgex.ErrEmpty) {
			return nil, nil
		}
		return nil, err
	}
	perCache.SetDefault(key, per)
	return per, nil
}

// GetPermissionById 根据 id 获取权限
func (dao *perDaoImpl) GetPermissionById(ctx context.Context, id int64) (*model.Permission, error) {
	key := fmt.Sprintf("id:%d", id)
	if per, found := perCache.Get(key); found {
		return per.(*model.Permission), nil
	}
	per := &model.Permission{}
	query := "SELECT id, name, per_type, router FROM permission WHERE id=? AND deleted_at=0"
	err := dao.db.Get(ctx, per, query, id)
	if err != nil {
		if errors.Is(err, pgex.ErrEmpty) {
			return nil, nil
		}
		return nil, err
	}
	perCache.SetDefault(key, per)
	return per, nil
}
